package com.rasenhund.android.grecorder.pref;

import java.util.ArrayList;

import android.app.ProgressDialog;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.widget.Toast;

import com.rasenhund.android.grecorder.R;
import com.rasenhund.android.grecorder.common.Const;
import com.rasenhund.android.grecorder.dao.RecordDao;
import com.rasenhund.android.grecorder.helper.DbHelper;
import com.rasenhund.android.grecorder.schema.Record;
import com.rasenhund.android.grecorder.schema.StageRecord;
import com.rasenhund.android.myutility.FileUtil;
import com.rasenhund.android.myutility.StringUtil;

/**
 * 設定画面 > リストア
 */
public class RestoreDialogPreference extends DialogPreference {
    // @SuppressWarnings("unused")
    // private static final String TAG =
    // RestoreDialogPreference.class.getSimpleName();
    // private final RestoreDialogPreference self = this;
    
    private Context mContext;

    /**
     * Constructor
     * 
     * @param context
     * @param attrs
     */
    public RestoreDialogPreference(Context context, AttributeSet attrs) {
        super(context, attrs);

        mContext = context;

        setDialogTitle("");
        setDialogMessage(mContext.getResources().getString(R.string.msg_restore_confirm));

    }

    /**
     * ダイアログクローズ時の処理
     */
    @Override
    protected void onDialogClosed(boolean positiveResult) {

        if (positiveResult) {

            // 復元タスクの実行
            doRestoreTask();

        }

        super.onDialogClosed(positiveResult);
    }

    /**
     * 復元タスク
     */
    private void doRestoreTask() {

        // 件数が多くなったときに応答していませんエラーになることがあるのでAsyncTask化

        AsyncTask<Void, Void, Void> restoreTask = new AsyncTask<Void, Void, Void>() {

            boolean mResult = false;
            ProgressDialog mProgressDialog = null;

            @Override
            protected void onPreExecute() {

                // ProgressDialogの表示
                mProgressDialog = new ProgressDialog(mContext);
                mProgressDialog.setMessage(mContext.getString(R.string.msg_restore_during));
                mProgressDialog.show();
                super.onPreExecute();

            }

            @Override
            protected Void doInBackground(Void... params) {

                // バックアップ実行
                mResult = restore();
                return null;

            }

            @Override
            protected void onPostExecute(Void result) {

                // ProgressDialogを閉じる
                mProgressDialog.dismiss();

                // メッセージ表示
                String sMsg = "";
                if (mResult) {
                    sMsg = mContext.getString(R.string.msg_restore_complete);
                } else {
                    sMsg = mContext.getString(R.string.msg_restore_failed);
                }
                Toast.makeText(mContext,
                        sMsg,
                        Toast.LENGTH_SHORT).show();

                super.onPostExecute(result);

            }

        };

        // タスク実行
        restoreTask.execute();

    }

    /**
     * 復元メイン処理
     * 
     * @return
     */
    private boolean restore() {

        Boolean bIsErr = false; // エラーフラグ

        ArrayList<Record> itemList = new ArrayList<Record>();   // 取り込む配列
        ArrayList<StageRecord> backup = new ArrayList<StageRecord>(); // バックアップ

        String sPath = Const.getCsvFilePath(mContext); // 入力ファイルのフルパス

        // データ読み込み
        String[] sData = FileUtil.readFile(sPath);

        // データの存在チェック
        if (sData == null || sData.length < 1) {
            bIsErr = true;
        }

        if (!bIsErr) {

            String[] sTmp; // 一時保存用の配列
            Record item = null;

            // ファイルのバージョンを取得
            int iVersion = Integer.valueOf(sData[0]);

            // バージョン別の項目数の取得
            int iColumns = 0;
            switch (iVersion) {
                case 1:
                    iColumns = 4;
                    break;
                case 2:
                    iColumns = 9;
                    break;
                case 3:
                    iColumns = 10;
                    break;
            }

            // 1行目はファイルバージョンなので2行目からデータ取得
            for (int i = 1; i < sData.length; i++) {

                sTmp = sData[i].split(",");

                if (sTmp.length != iColumns) {
                    // 要素数エラー
                    bIsErr = true;
                    break;
                }

                item = new Record();

                // データの型チェック
                try {

                    // ステージコード、カテゴリコード、結果コード、登録日
                    item.setStageCd(Integer.parseInt(sTmp[0]));
                    item.setCategoryCd(Integer.parseInt(sTmp[1]));
                    item.setResultCd(Integer.parseInt(sTmp[2]));
                    item.setInsertDate(sTmp[3]);

                    if (iVersion >= 2) {

                        // 対戦人数、ポイント、ランクコード、メモ、集計対象外フラグ
                        item.setVersus(Integer.parseInt(sTmp[4]));
                        item.setPoint(Integer.parseInt(sTmp[5]));
                        item.setRankCd(Integer.parseInt(sTmp[6]));
                        // Base64エンコードしてCSV出力しているためデコード処理を行う
                        item.setMemo(StringUtil.decodeFromBase64(sTmp[7]));
                        // TODO: 未使用項目なのでデフォルトの0を入れておく（実装したら元に戻す）
                        // item.setExcludeFlg(Integer.parseInt(sTmp[8]));
                        item.setExcludeFlg(0);

                    }

                    if (iVersion >= 3) {

                        // 軍属コード
                        item.setArmyCd(Integer.parseInt(sTmp[9]));

                    }

                } catch (Exception e) {

                    // 数値項目のParseで例外が発生した場合は不正データとして処理中断
                    bIsErr = true;
                    break;

                }

                itemList.add(item);
                
            }
        }

        if (!bIsErr) {

            // 表示用データの取得
            DbHelper dbHelper = null;
            SQLiteDatabase db = null;

            try {

                dbHelper = new DbHelper(mContext);
                db = dbHelper.getWritableDatabase();
                RecordDao dao = new RecordDao(db);

                // バックアップ取得
                backup = dao.selectAll();

                // データ削除
                dao.deleteAll();

                // CSVファイルのデータをInsert
                for (int i = 0; i < itemList.size(); i++) {

                    if (dao.insert((Record) (itemList.get(i))) == 0) {
                        bIsErr = true;
                        break;
                    }

                }

                if (bIsErr) {

                    // エラー発生時はバックアップから復元

                    // 一度データをクリア
                    dao.deleteAll();

                    // バックアップを再度Insert
                    for (int i = 0; i < backup.size(); i++) {
                        dao.insert(backup.get(i));
                    }

                }

            } finally {
                if (db.isOpen()) {
                    db.close();
                }
            }

        }
        
        if (bIsErr) {
            return false;
        }
        
        return true;

    }

}
